package com.sugon.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.sugon.dao.SparePartDao;
import com.sugon.dao.SparePartRequDao;
import com.sugon.dao.SparePartRequDetailDao;
import com.sugon.entity.*;
import com.sugon.modules.sparepart.consts.SparePartNeedsPlanProgress;
import com.sugon.modules.sparepart.consts.SparePartNeedsPlanType;
import com.sugon.modules.sparepart.model.vo.SparePartRequDetailVO;
import com.sugon.service.*;
import com.sugon.utils.ShiroUtils;
import com.sugon.utils.excel.ExcelImport;
import org.apache.shiro.util.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 备件需求计划Service实现类
 *
 * @author sugon
 * @date 2019-08-02 14:31:17
 */
@Service("sparePartRequService")
public class SparePartRequServiceImpl implements SparePartRequService {

    @Autowired
    private SparePartRequDao sparePartRequDao;
    @Autowired
    private SparePartDao sparePartDao;
    @Autowired
    private SparePartRequDetailDao sparePartRequDetailDao;
    @Autowired
    private SysDeptService deptService;
    @Autowired
    private SparePartRequDetailService sparePartRequDetailService;
    @Autowired
    private SparePartService sparePartService;
    @Autowired
    private SysUserService userService;

    @Override
    public List<SparePartRequDetailVO> queryAllByPlanIds(String planIds) {
        List<SparePartRequDetailVO> sparePartNeedsItemList = CollectionUtil.newArrayList();
        if (StrUtil.isNotEmpty(planIds)) {
            List<String> planIdList = StrUtil.split(planIds, ',');
            // 更新已导出状态
            for (String planId : planIdList) {
                Map<String, Object> param = new HashMap<>(2);
                param.put("isExported", 1);
                param.put("id", planId);
                sparePartRequDao.update(param);
            }
            Map<String, Object> param = new HashMap<>(1);
            param.put("planIdList", planIdList);
            sparePartNeedsItemList.addAll(sparePartRequDetailDao.listAll(param));
        }
        return sparePartNeedsItemList;
    }

    @Override
    public boolean isExists(Map<String, Object> params) {
        return queryTotal(params) > 0;
    }

    @Override
    public String generateUniqueCode(Object object) {
        SparePartRequEntity sparePartRequ = (SparePartRequEntity) object;
        String planCode = sparePartRequ.getPlanCode();
        if (StrUtil.isEmpty(planCode)) {
            String workshop = ShiroUtils.getWorkshop();
            Assert.notNull(workshop, "只有处于某部门下的用户执行该操作！");
            // 设置备件需求计划编码
            SysDeptEntity deptEntity = deptService.queryObject(workshop);
            Assert.notNull(deptEntity, "非法所属部门编码！");
            planCode = deptEntity.getDcode() + "-" + sparePartRequ.getOrganMonth().replace("-", "");
        }
        String matchedMaxPlanCode = sparePartRequDao.queryMatchedMaxPlanCode(planCode);
        if (StrUtil.isNotEmpty(matchedMaxPlanCode)) {
            planCode = com.sugon.modules.utils.StrUtil.increase(matchedMaxPlanCode, planCode + "-", 1, 1);
        }
        return planCode;
    }

    @Override
    public SparePartRequEntity queryObject(String id) {
        return sparePartRequDao.queryObject(id);
    }

    @Override
    public SparePartRequEntity queryObjectByCode(String code) {
        Map<String, Object> param = new HashMap<>(1);
        param.put("planCode", code);
        List<SparePartRequEntity> needsList = sparePartRequDao.queryList(param);
        return CollectionUtil.isNotEmpty(needsList) ? needsList.get(0) : null;
    }

    @Override
    public SparePartRequEntity queryByProcInstId(String procInstId) {
        Map<String, Object> param = new HashMap<>(1);
        param.put("procInstId", procInstId);
        List<SparePartRequEntity> needsList = sparePartRequDao.queryList(param);
        return CollectionUtil.isNotEmpty(needsList) ? needsList.get(0) : null;
    }

    @Override
    public List<SparePartRequEntity> queryList(Map<String, Object> map) {
        return sparePartRequDao.queryList(map);
    }

    @Override
    public int queryTotal(Map<String, Object> map) {
        return sparePartRequDao.queryTotal(map);
    }

    @Override
    public int save(SparePartRequEntity sparePartRequ) {
        sparePartRequ.setPlanCode(generateUniqueCode(sparePartRequ));
        // 设置编制人信息
        SysUserEntity user = ShiroUtils.getUserEntity();
        sparePartRequ.setApplyUnit(user.getDeptId());
        sparePartRequ.setOrganId(ShiroUtils.getWorkshop());
        sparePartRequ.setOrganUser(user.getUserId());
        // 如果是终版计划，那么不需要审核
        if (EnumUtil.equals(SparePartNeedsPlanType.RESULT, sparePartRequ.getPlanType())) {
            sparePartRequ.setProgress(SparePartNeedsPlanProgress.PASSED);
        } else {
            sparePartRequ.setProgress(SparePartNeedsPlanProgress.NEW);
        }
        // 设置基础信息
        sparePartRequ.setId(RandomUtil.randomString(32));
        sparePartRequ.setCreateTime(DateUtil.date());
        sparePartRequ.setCreateUser(user.getUserId());
        sparePartRequ.setDelFlag(1);
        // 默认未导出
        sparePartRequ.setIsExported(0);
        // 保存备件需求计划
        return sparePartRequDao.save(sparePartRequ);
    }

    @Override
    public int update(SparePartRequEntity sparePartRequ) {
        sparePartRequ.setUpdateUser(ShiroUtils.getUserId());
        sparePartRequ.setUpdateDate(DateUtil.date());
        return sparePartRequDao.update(sparePartRequ);
    }

    @Override
    public int delete(String id) {
        return sparePartRequDao.delete(id);
    }

    @Override
    public int deleteBatch(String[] ids) {
        if (ArrayUtil.isEmpty(ids)) {
            return 0;
        }
        int num = 0;
        for (String requId : ids) {
            sparePartRequDetailDao.deleteByPlanId(requId);
            num += sparePartRequDao.delete(requId);
        }
        return num;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int importSparePartNeedsPlanItemList(SparePartRequEntity sparePartNeedsPlan, MultipartFile file) {
        List<String[]> list = ExcelImport.getExcelData(file);
        int count = 0;
        if (CollectionUtil.isNotEmpty(list)) {

            Map<String, String> deptMap = new HashMap<>();

            // 备件编码列表，用户重新计算在途数
            Set<String> sparePartCodeList = new HashSet<>();

            // 先删除当前计划的所有明细
            sparePartRequDetailDao.deleteByPlanId(sparePartNeedsPlan.getId());
            // 从第二行开始
            for (int i = 1; i < list.size(); i++) {
                String[] array = list.get(i);
                array = ArrayUtil.resize(array, 20);
                // 根据备件编码查询备件是否存在，如果存在更新备件的ERP编码和规格信息
                SparePartEntity sparePart = sparePartService.queryByCode(array[2]);
                if (sparePart == null) {
                    continue;
                }
                if (StrUtil.isNotEmpty(array[3])) {
                    sparePart.setErpCode(array[3]);
                }
                if (StrUtil.isNotEmpty(array[5])) {
                    sparePart.setSpec(array[5]);
                }
                if (StrUtil.isNotEmpty(sparePart.getErpCode()) || StrUtil.isNotEmpty(sparePart.getSpec())) {
                    sparePartService.update(sparePart);
                }
                SparePartRequDetailEntity item = new SparePartRequDetailEntity();
                // 设置编制人
                SysUserEntity organUser = userService.queryByNickname(array[0]);
                if (organUser != null) {
                    item.setOrganUser(organUser.getUserId());
                }
                // 设置备件实际需求单位
                if (StrUtil.isNotEmpty(array[1])) {
                    if (!deptMap.containsKey(array[1])) {
                        List<SysDeptEntity> deptList = deptService.getByName(array[1]);
                        if (CollectionUtil.isNotEmpty(deptList)) {
                            deptMap.put(array[1], deptList.get(0).getDeptId());
                        }
                    }
                    item.setApplyDept(deptMap.get(array[1]));
                }

                item.setPlanId(sparePartNeedsPlan.getId());
                item.setPlanCode(sparePartNeedsPlan.getPlanCode());
                item.setMaterialCode(array[2]);
                item.setMaterialId(sparePart.getId());
                item.setDemandNum(Integer.parseInt(array[12]));
                if (StrUtil.isNotEmpty(array[13])) {
                    item.setPlaneTime(DateUtil.parseDate(array[13]));
                }
                // 如果计划价格未填写，默认取当时备件的价格
                if (StrUtil.isNotEmpty(array[15])) {
                    item.setPlanPrice(Double.parseDouble(array[15]));
                } else {
                    BigDecimal price = sparePart.getPrice();
                    if (price != null) {
                        item.setPlanPrice(price.doubleValue());
                    }
                }
                item.setTransitNum(item.getDemandNum());
                item.setInboundNum(0);
                item.setIsCancelTransit(0);
                // 审核意见：
                /*
                    一般来说审核意见都会是空的
                    长安内部有个科室是专门用来画备件的，即他们把备件采购过来后，会根据采购的备件进行制图
                    一旦采购过一次后，就不会再次采购；所以要求一旦采购的备件入库，需要及时告知备件专员
                    此时这个字段会设置值0或者1，表示这个备件入库后需要及时通知对应车间的备件专员的意思
                 */
                item.setRemark(array[17]);
                // 计划编码
                item.setBusinessCode(array[18]);
                // 记录导入条数
                count += sparePartRequDetailService.save(item);
                // 记录备件列表
                sparePartCodeList.add(item.getMaterialCode());
            }
            for (String sparePartCode : sparePartCodeList) {
                // 更新下备件在途数
                sparePartDao.realtimeUpdateTransitNum(sparePartCode);
            }
        }
        return count;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateOrderGenerateTime(SparePartRequEntity sparePartNeedsPlan, MultipartFile file) {
        List<String[]> list = ExcelImport.getExcelData(file);
        int count = 0;
        if (CollectionUtil.isNotEmpty(list)) {
            // 获取备件交货周期map
            List<SparePartCategory> sparePartCategories = sparePartDao.listCategory();
            // 备件发货周期MAP
            Map<String, Integer> sparePartDeliveryCycleMap = sparePartCategories.stream().collect(Collectors.toMap(SparePartCategory::getId, SparePartCategory::getDeliveryCycle));
            // 备件分类MAP
            Map<String, String> sparePartCategoryMap = sparePartCategories.stream().collect(Collectors.toMap(SparePartCategory::getName, SparePartCategory::getId));

            // 从第二行开始
            for (int i = 1; i < list.size(); i++) {
                String[] array = list.get(i);
                array = ArrayUtil.resize(array, 20);
                // 根据备件编码查询备件是否存在，如果存在更新备件的ERP编码和规格信息
                SparePartEntity sparePart = sparePartService.queryByCode(array[2]);
                if (sparePart == null) {
                    continue;
                }
                // 如果导入的备件分类不为空，则有必要更新下对应备件的分类信息
                if (StrUtil.isNotEmpty(array[8])) {
                    String spCategoryId = sparePartCategoryMap.get(array[8]);
                    if (StrUtil.isNotEmpty(spCategoryId) && !StrUtil.equals(spCategoryId, sparePart.getInstallPosition())) {
                        sparePart.setInstallPosition(spCategoryId);
                        sparePartService.update(sparePart);
                    }
                }
                // 如果备件未配置分类，那么不进行后续更新
                if (StrUtil.isEmpty(sparePart.getInstallPosition())) {
                    continue;
                }
                // 排除掉之前设置的信息有误的情况
                Integer deliveryCycle = sparePartDeliveryCycleMap.get(sparePart.getInstallPosition());
                if (deliveryCycle == null) {
                    continue;
                }
                // 如果计划编码 + 订单生成时间 这两列有任意一个为空，则不执行后续逻辑
                if (!StrUtil.isAllNotBlank(array[18], array[19])) {
                    continue;
                }
                // 根据计划编码获取终版需求计划明细
                SparePartRequDetailEntity detail = sparePartRequDetailDao.queryByBusinessCode(array[18]);
                if (detail == null) {
                    continue;
                }
                // 只更新订单生成时间+预计到货时间
                SparePartRequDetailEntity newDetail = new SparePartRequDetailEntity();
                newDetail.setId(detail.getId());
                if (StrUtil.isNotEmpty(array[13])) {
                    newDetail.setPlaneTime(DateUtil.parseDate(array[13]));
                }
                // 设置订单生成时间
                newDetail.setOrderGenerateTime(DateUtil.parseDate(array[19]));
                // 设置预计交货时间
                newDetail.setArriveTime(DateUtil.offsetDay(newDetail.getOrderGenerateTime(), deliveryCycle));
                // 记录导入条数
                count += sparePartRequDetailService.update(newDetail);
            }
        }
        return count;
    }
}
